import type { AxiosRequestConfig } from 'axios'
import axios from 'axios'

import { message as AMessage } from 'antd'
// import { useCommonStore } from '@/stores/common'

// import { paths } from '@/config/paths'

const { VITE_BASE_URL } = import.meta.env

window.requests = []
window.tokenRefreshing = false
const pendingMap = new Map()
const loadingInstance: ILoadingInstance = {
  target: null,
  count: 0,
}

const TIMEOUT = 60 * 1000

const defaultOption = {
  // 是否开启取消重复请求, 默认为 true
  CancelDuplicateRequest: true,
  // 是否开启loading层效果, 默认为false
  loading: false,
  // 是否开启简洁的数据结构响应, 默认为true
  reductDataFormat: true,
  // 是否开启接口错误信息展示,默认为true
  showErrorMessage: true,
  // 是否开启code不为1时的信息提示, 默认为true
  showCodeMessage: true,
  // 是否开启code为1时的信息提示, 默认为false
  showSuccessMessage: false,
  // 当前请求使用另外的用户token
  anotherToken: '',
}

/**
 * 创建`Axios`
 * 默认开启`reductDataFormat(简洁响应)`,返回类型为`ApiPromise`
 * 关闭`reductDataFormat`,返回类型则为`AxiosPromise`
 */

export function createAxios<Data = any, T = ApiPromise<Data>>(
  axiosConfig: AxiosRequestConfig,
  options: IOptions = {},
  loading: any = {},
): T {
  const instance = axios.create({
    baseURL: VITE_BASE_URL,
    timeout: TIMEOUT,
  })

  options = {
    ...defaultOption,
    ...options,
  }

  // 请求拦截
  instance.interceptors.request.use(
    (config) => {
      removePending(config)
      options.CancelDuplicateRequest && addPending(config)
      // 创建loading实例
      if (options.loading) {
        loadingInstance.count++
        if (loadingInstance.count === 1) {
          // loadingInstance.target = ElLoading.service(loading)
        }
      }

      // if (config.headers) {
      //   const { token, jti } = useCommonStore.getState()
      //   if (token)
      //     config.headers.Authorization = `Bearer ${token}`
      //   if (jti)
      //     config.headers.jti = jti
      // }

      return config
    },
    (error) => {
      return Promise.reject(error)
    },
  )

  // 响应拦截
  instance.interceptors.response.use(
    (response) => {
      removePending(response.config)
      // 关闭loading
      options.loading && closeLoading(options)

      if (response.config.responseType === 'json') {
        // 判断接口状态码
        if (response.data && response.data.status !== 200) {
          if (options.showCodeMessage) {
            // ElNotification({
            //   type: 'error',
            //   message: response.data.msg,
            // })
          }

          // code不等于1, 页面then内的具体逻辑就不执行了
          return Promise.reject(response.data)
        } else if (
          options.showSuccessMessage
          && response.data
          && response.data.code == 1
        ) {
          // ElNotification({
          //   message: response.data.msg ? response.data.msg : '操作成功',
          //   type: 'success',
          // })
        }
      }

      return options.reductDataFormat ? response.data : response
    },
    (error) => {
      error.config && removePending(error.config)
      // 关闭loading
      options.loading && closeLoading(options)
      // 处理错误状态码
      options.showErrorMessage && httpErrorStatusHandle(error)
      // 错误继续返回给到具体页面
      return Promise.reject(error)
    },
  )
  return instance(axiosConfig) as T
}

/**
 * 处理异常
 * @param {*} error
 */
function httpErrorStatusHandle(error: any) {
  // const {
  //   clearJti,
  //   clearToken,
  //   clearUserInfo,
  // }
  // = useCommonStore.getState()

  // 处理被取消的请求
  if (axios.isCancel(error))
    return console.error(`因为请求重复被自动取消：${error.message}`)

  let message: string = ''

  if (error && error.response) {
    switch (error.response.status) {
      case 302:
        message = '接口重定向了！'
        break
      case 400:
        message = '参数不正确！'
        break
      case 401:
        // let errMsg: any = error.response.data && error.response.data.ErrorMsg
        // message = `状态码401: ${errMsg}`

        message = '登录状态已过期，请重新登录'

        // clearToken()
        // clearJti()
        // clearUserInfo()
        // window.location.replace(paths.login.getHref(window.location.pathname + window.location.search))

        break
      case 403:
        message = '您没有权限操作！'
        break
      case 404:
        message = `请求地址出错: ${error.response.config.url}`
        break
      case 408:
        message = '请求超时！'
        break
      case 409:
        message = '系统已存在相同数据！'

        break
      case 500:
        message = '服务器内部错误！'
        break
      case 501:
        message = '服务未实现！'
        break
      case 502:
        message = '网关错误！'
        break
      case 503:
        message = '服务不可用！'
        break
      case 504:
        message = '服务暂时无法访问，请稍后再试！'
        break
      case 505:
        message = 'HTTP版本不受支持！'
        break
      default:
        message = '异常问题，请联系网站管理员！'
        break
    }
  }
  if (error.message.includes('timeout'))
    message = '网络请求超时！'
  if (error.message.includes('Network'))
    message = window.navigator.onLine ? '服务端异常！' : '您断网了！'

  if (message) {
    AMessage.error(message)
  }
}

/**
 * 关闭Loading层实例
 */
function closeLoading(options: IOptions) {
  if (options.loading && loadingInstance.count > 0)
    loadingInstance.count--
  if (loadingInstance.count === 0) {
    loadingInstance.target.close()
    loadingInstance.target = null
  }
}

/**
 * 储存每个请求的唯一cancel回调, 以此为标识
 */
function addPending(config: AxiosRequestConfig) {
  const pendingKey = getPendingKey(config)
  config.cancelToken
    = config.cancelToken
    || new axios.CancelToken((cancel) => {
      if (!pendingMap.has(pendingKey)) {
        pendingMap.set(pendingKey, cancel)
      }
    })
}

/**
 * 删除重复的请求
 */
function removePending(config: AxiosRequestConfig) {
  const pendingKey = getPendingKey(config)
  if (pendingMap.has(pendingKey)) {
    const cancelToken = pendingMap.get(pendingKey)
    cancelToken(pendingKey)
    pendingMap.delete(pendingKey)
  }
}

/**
 * 生成每个请求的唯一key
 */
function getPendingKey(config: AxiosRequestConfig) {
  let { data } = config
  const {
    url,
    method,
    params,
    headers,
  } = config
  if (typeof data === 'string')
    // response里面返回的config.data是个字符串对象
    data = JSON.parse(data)
  return [
    url,
    method,
    headers && (headers as anyObj).batoken ? (headers as anyObj).batoken : '',
    headers && (headers as anyObj)['ba-user-token']
      ? (headers as anyObj)['ba-user-token']
      : '',
    headers && (headers as anyObj).authorization
      ? (headers as anyObj).authorization
      : '',
    JSON.stringify(params),
    JSON.stringify(data),
  ].join('&')
}

interface ILoadingInstance {
  target: any
  count: number
}
interface IOptions {
  /** 是否开启取消重复请求, 默认为 true */
  CancelDuplicateRequest?: boolean
  /** 是否开启loading层效果, 默认为false */
  loading?: boolean
  /** 是否开启简洁的数据结构响应, 默认为true */
  reductDataFormat?: boolean
  /** 是否开启接口错误信息展示,默认为true */
  showErrorMessage?: boolean
  /** 是否开启code不为0时的信息提示, 默认为true */
  showCodeMessage?: boolean
  /** 是否开启code为0时的信息提示, 默认为false */
  showSuccessMessage?: boolean
  /** 当前请求使用另外的用户token */
  anotherToken?: string
}

/*
 * 感谢掘金@橙某人提供的思路和分享
 * 本axios封装详细解释请参考：https://juejin.cn/post/6968630178163458084?share_token=7831c9e0-bea0-469e-8028-b587e13681a8#heading-27
 */
